﻿using System;

namespace Heimdallr
{
    /// <summary>
    /// Provides data for events that prepresent completed and successful operation.
    /// </summary>
    /// <remarks>
    /// For the generic version of this class, see <see cref="CompletedEventArgs{T}"/>.
    /// </remarks>
    public class CompletedEventArgs : EventArgs
    {
        #region Field

        /// <summary>
        /// Gets the empty instance of this class.
        /// This field is read-only.
        /// </summary>
        public static readonly CompletedEventArgs Completed = new CompletedEventArgs();

        private readonly object userState;

        #endregion

        #region Property

        /// <summary>
        /// Gets a value that represents the user state.
        /// </summary>
        public object UserState
        {
            get { return this.userState; }
        }

        #endregion

        #region Constructor

        /// <summary>
        /// Initializes a new instance of this class.
        /// </summary>
        public CompletedEventArgs()
        {
        }

        /// <summary>
        /// Initializes a new instance of this class, using specified user state.
        /// </summary>
        /// <param name="userState">A specified user state.</param>
        public CompletedEventArgs(object userState)
        {
            this.userState = userState;
        }

        #endregion

        #region Other
         
        /// <summary>
        /// Create a new instance of <see cref="CompletedEventArgs{T}"/> class, using specified user state.
        /// </summary>
        /// <typeparam name="TState">Type of the value that represents the user state.</typeparam>
        /// <param name="userState">A specified user state.</param>
        /// <returns>A new instace with specified user state.</returns>
        public static CompletedEventArgs<TState> Create<TState>(TState userState)
        {
            return new CompletedEventArgs<TState>(userState);
        }

        #endregion
    }
     
    /// <summary>
    /// Provides data for events prepresent completed and successful.
    /// </summary>
    /// <remarks>
    /// This class is the generic version of <see cref="CompletedEventArgs"/>.
    /// </remarks> 
    /// <typeparam name="TState">Type of the value that represents the user state.</typeparam>
    public class CompletedEventArgs<TState> : EventArgs
    {
        #region Field

        private readonly TState state;
        
        #endregion

        #region Property

        /// <summary>
        /// Gets a value that represents the user state.
        /// </summary>
        public TState UserState
        {
            get { return this.state; }
        }

        #endregion

        #region Constructor

        /// <summary>
        /// Initializes a new instance of this class.
        /// </summary>
        public CompletedEventArgs()
            : this(default(TState))
        {
        }

        /// <summary>
        /// Initializes a new instance of this class, using specified user state.
        /// </summary>
        /// <param name="userState">A specified user state.</param>
        public CompletedEventArgs(TState state)
        {
            this.state = state;
        }

        #endregion
    }

    /// <summary>
    /// Represents the method that will handle the event of an completed and successful operation.
    /// </summary>
    /// <typeparam name="TState">Type of the value that represents the user state.</typeparam>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">A <see cref="CompletedEventArgs{T}"/> that contains the event data.</param>
    public delegate void CompletedEventHandler<TState>(object sender, CompletedEventArgs<TState> e);
}